package com.xncoding.trans.service;

import com.xncoding.trans.dao.entity.User;
import com.xncoding.trans.dao.repository.UserMapper;
import com.xncoding.trans.exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

@Service
@Transactional(readOnly = true)
public class UserService {
    @Resource
    private UserMapper userMapper;

    @Autowired
    private TransactionTemplate primaryTransactionTemplate;

    @Autowired
    @Qualifier("secondaryTransactionTemplate")
    private TransactionTemplate secondaryTransactionTemplate;

    @Autowired
    private PlatformTransactionManager primaryTransactionManager;

    @Autowired
    @Qualifier("secondaryTransactionManager")
    private PlatformTransactionManager secondaryTransactionManager;

    public User getById(int id) {
        return userMapper.selectById(id);
    }

    /**
     * 增删改要写 ReadOnly=false 为可写
     * @param user 用户
     */
    @Transactional(readOnly = false)
    public void updateUserError(User user) {
        userMapper.updateById(user);
        errMethod(); // 执行一个会抛出异常的方法
    }

    @Transactional(readOnly = false, noRollbackFor = {MyException.class})
    public void updateUserError2(User user) {
        userMapper.updateById(user);
        errMethod2(); // 执行一个会抛出自定义异常的方法
    }

    /**
     * 在多数据源场景下，事务传播行为同样适用。例如，如果一个方法调用另一个跨数据源的事务方法，需要合理配置事务传播行为以确保数据的一致性
     */
//    @Transactional(value = "primaryTransactionManager", propagation = Propagation.REQUIRES_NEW)
    public void complexOperation() {
        // 调用另一个数据源的事务方法
    }
    public void updateProductInPrimary() {
        primaryTransactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                try {
                    // 使用primaryDataSource对应的Mapper进行数据库操作
                    return null;
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

    public void placeOrderInPrimary() {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = primaryTransactionManager.getTransaction(def);
        try {
            // 使用primaryDataSource/DruidDataSource对应的Mapper进行数据库操作
            primaryTransactionManager.commit(status);
        } catch (Exception e) {
            primaryTransactionManager.rollback(status);
            throw e;
        }
    }


    private void errMethod() {
        System.out.println("error");
        throw new RuntimeException("runtime");
    }
    private void errMethod2() {
        System.out.println("error");
        throw new MyException("runtime");
    }
}
